package org.cbyyx.tc.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.cbyyx.tc.annotation.AuthCheck;
import org.cbyyx.tc.common.BaseResponse;
import org.cbyyx.tc.common.ResultUtils;
import org.cbyyx.tc.constant.UserConstant;
import org.cbyyx.tc.enums.ErrorCode;
import org.cbyyx.tc.exception.BusinessException;
import org.cbyyx.tc.exception.ThrowUtils;
import org.cbyyx.tc.model.dto.orderRequest.OrderCreateRequest;
import org.cbyyx.tc.model.dto.orderRequest.OrderQueryRequest;
import org.cbyyx.tc.model.vo.orderResponse.OrderDetailVO;
import org.cbyyx.tc.service.OrderService;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

/**
 * 订单管理
 * @author cbyyx
 * @since 2025-4-27
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/orders")
public class OrderController {

    private final OrderService orderService;

    /**
     * 创建订单
     * @param request 订单创建请求参数，包含商品信息和收货地址
     * @return 包含订单详情的响应
     * @throws BusinessException 当请求参数为空或业务逻辑校验失败时抛出
     */
    @AuthCheck(role = UserConstant.USER)
    @PostMapping
    public BaseResponse<OrderDetailVO> createOrder(@RequestBody @Valid OrderCreateRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR, "请求参数不能为空");
        return ResultUtils.success(orderService.createOrder(request));
    }

    /**
     * 取消订单
     * @param orderId 订单ID
     * @return 是否取消成功
     * @throws BusinessException 当订单ID无效或业务逻辑校验失败时抛出
     */
    @AuthCheck(role = UserConstant.USER)
    @PutMapping("/{orderId}/cancel")
    public BaseResponse<Boolean> cancelOrder(@PathVariable Long orderId) {
        ThrowUtils.throwIf(orderId == null || orderId <= 0, ErrorCode.PARAMS_ERROR, "订单ID无效");
        return ResultUtils.success(orderService.cancelOrder(orderId));
    }

    /**
     * 获取订单详情
     * @param orderId 订单ID
     * @return 包含订单详情的响应
     * @throws BusinessException 当订单ID无效或订单不存在时抛出
     */
    @AuthCheck(role = UserConstant.USER)
    @GetMapping("/{orderId}")
    public BaseResponse<OrderDetailVO> getOrderDetail(@PathVariable Long orderId) {
        ThrowUtils.throwIf(orderId == null || orderId <= 0, ErrorCode.PARAMS_ERROR, "订单ID无效");
        return ResultUtils.success(orderService.getOrderDetail(orderId));
    }

    /**
     * 查询订单列表
     * @param request 订单查询请求参数
     * @return 分页订单列表响应
     * @throws BusinessException 当查询参数为空时抛出
     */
    @AuthCheck(role = UserConstant.USER)
    @GetMapping("/list")
    public BaseResponse<Page<OrderDetailVO>> listOrders(@Valid OrderQueryRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR, "查询参数不能为空");
        return ResultUtils.success(orderService.listOrders(request));
    }

    /**
     * 支付订单
     * @param orderId 订单ID
     * @return 是否支付成功
     * @throws BusinessException 当订单ID无效或业务逻辑校验失败时抛出
     */
    @AuthCheck(role = UserConstant.USER)
    @PutMapping("/{orderId}/pay")
    public BaseResponse<Boolean> payOrder(@PathVariable Long orderId) {
        ThrowUtils.throwIf(orderId == null || orderId <= 0, ErrorCode.PARAMS_ERROR, "订单ID无效");
        return ResultUtils.success(orderService.payOrder(orderId));
    }

    /**
     * 订单发货
     * @param orderId 订单ID
     * @return 是否发货成功
     * @throws BusinessException 当订单ID无效或业务逻辑校验失败时抛出
     * @apiNote 仅商户角色可调用此接口
     */
    @AuthCheck(role = UserConstant.MERCHANT)
    @PutMapping("/{orderId}/deliver")
    public BaseResponse<Boolean> deliverOrder(@PathVariable Long orderId) {
        ThrowUtils.throwIf(orderId == null || orderId <= 0, ErrorCode.PARAMS_ERROR, "订单ID无效");
        return ResultUtils.success(orderService.deliverOrder(orderId));
    }

    /**
     * 完成订单
     * @param orderId 订单ID
     * @return 是否完成成功
     * @throws BusinessException 当订单ID无效或业务逻辑校验失败时抛出
     */
    @AuthCheck(role = UserConstant.USER)
    @PutMapping("/{orderId}/complete")
    public BaseResponse<Boolean> completeOrder(@PathVariable Long orderId) {
        ThrowUtils.throwIf(orderId == null || orderId <= 0, ErrorCode.PARAMS_ERROR, "订单ID无效");
        return ResultUtils.success(orderService.completeOrder(orderId));
    }
}